//  This file is part of Swordbible - http://www.swordwarrior.net
//  Copyright (C) 2003-2009 Manu Mital mital.manu@gmail.com

//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2, or (at your option)
//  any later version.

//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.

//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


// ParallelBible.cpp : implementation file
//

#include <stdafx.h>
#include "SwordBible.h"
#include "ParallelBible.h"
#include "BibleForm.h"


// CParallelBible dialog

IMPLEMENT_DYNAMIC(CParallelBible, CPropertyPage)

CParallelBible::CParallelBible()
	: CPropertyPage(CParallelBible::IDD)
{
	   rect.top = 40;
     rect.left = 10;
}

CParallelBible::~CParallelBible()
{
}

void CParallelBible::DoDataExchange(CDataExchange* pDX)
{
  CPropertyPage::DoDataExchange(pDX);
  DDX_Control(pDX, IDC_EXPLORER_PARALLEL, m_browser);
}


BEGIN_MESSAGE_MAP(CParallelBible, CPropertyPage)
	ON_COMMAND(ID_PARALLEL_SELECTALL, OnSelectAll)
	ON_COMMAND(ID_PARALLEL_PRINT,OnPrint)
    ON_COMMAND(ID_PARALLEL_COPY, OnCopy)
	ON_COMMAND(ID_PARALLEL_PREVIOUS,OnPrevious)
	ON_COMMAND(ID_PARALLEL_NEXT,OnNext)
	ON_COMMAND(ID_DROPDOWN_VERSIONS, OnShowVersions)
	ON_MESSAGE(ID_BIBLEPAGE_COMMAND,OnMainFrameCommand)
    ON_COMMAND(ID_PARALLEL_ZOOM, OnZoom)
	ON_UPDATE_COMMAND_UI(ID_PARALLEL_ZOOM, OnUpdateZoom)
	ON_WM_SIZE()

	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
   ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
  
  END_MESSAGE_MAP()


// CParallelBible message handlers

BOOL CParallelBible::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	m_browser.CreateFromControl(this,IDC_EXPLORER_PARALLEL);



	for(int i = 0; i < CSwordBibleDoc::numBiblesAvailable; i++)
		BibleActive[i] = FALSE;


    if (!m_wndFormatBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD
       | WS_VISIBLE | CBRS_TOP |  CBRS_FLYBY | CBRS_TOOLTIPS) ||
       !m_wndFormatBar.LoadToolBar(IDR_PARALLEL_TOOLBAR))
   {
      TRACE0("Failed to create toolbar\n");
      return -1;      // fail to create
   }

   // buttons size: 16
   // bitmaps:
   // enabled - IDB_TOOLBAR_NORMAL
   // hovered - IDB_TOOLBAR_HOT
   // disabled - IDB_TOOLBAR_DISABLED
   // transparent color RGB(255, 0, 255)
   m_wndFormatBar.LoadTCToolBar(24, IDB_BITMAP_PARALLEL,IDB_BITMAP_PARALLEL,
                              IDB_BITMAP_PARALLEL, RGB(255,255,255));




	// Position the control bars using RepositionBars. 
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);

	// Expand the size of the Toolbar window so all controls in it would fit
	
	CRect toolBarRect;
	CToolBarCtrl& formatBar = m_wndFormatBar.GetToolBarCtrl();
	formatBar.GetWindowRect(toolBarRect);
	ScreenToClient(toolBarRect);
	toolBarRect.left += 10  ;
	toolBarRect.right += 500  ;
	formatBar.MoveWindow(toolBarRect,TRUE);


	
	return TRUE;


}
void CParallelBible::OnSize(UINT nType, int cx, int cy)
{
	CPropertyPage::OnSize(nType, cx, cy);

	// resize the grid  control
	if( ::IsWindow( m_browser.GetSafeHwnd()))
  {
    rect.right = rect.left + cx - 20;
    rect.bottom = rect.top + cy - 50;
	  m_browser.SetWindowPos(NULL,10,40,cx-20,cy-50,SWP_NOZORDER | SWP_NOACTIVATE);
  }


	

}

void CParallelBible::OnPrint()
{

	// only the active page should handle the message
		if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;
	
   m_browser.PrintPreview();
	  
	
}

void CParallelBible::OnPrevious()
{
  
	int chap = CSwordBibleDoc::key.Chapter();
	CSwordBibleDoc::key.Chapter(chap - 1);
	
	showText();

	CWnd * pWnd = AfxGetMainWnd();

	if(CSwordBibleDoc::notesSynch)
	{
	CNotesPage::ActiveMainFrameCommand = _T("BibleSynch");
	pWnd->SendMessageToDescendants(ID_NOTES_COMMAND,0,0);
	}

	if(CSwordBibleDoc::bottomSynch)
	{
	CBottomPage::ActiveMainFrameCommand = _T("BibleSynch");
	pWnd->SendMessageToDescendants(ID_COMMENTARY_COMMAND,0,0);
	}

  

}

void CParallelBible::OnNext()
{
    int chap = CSwordBibleDoc::Chapter();
	CSwordBibleDoc::key.Chapter(chap + 1);
	
	showText();

	CWnd * pWnd = AfxGetMainWnd();

	if(CSwordBibleDoc::notesSynch)
	{
	CNotesPage::ActiveMainFrameCommand = _T("BibleSynch");
	pWnd->SendMessageToDescendants(ID_NOTES_COMMAND,0,0);
	}

	if(CSwordBibleDoc::bottomSynch)
	{
	CBottomPage::ActiveMainFrameCommand = _T("BibleSynch");
	pWnd->SendMessageToDescendants(ID_COMMENTARY_COMMAND,0,0);
	}
  

}

void CParallelBible::OnCopy(void) 
{

  // only the active page should handle the message
  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

  m_browser.Copy();
}

void CParallelBible::OnZoom()
{
	// only the active page should handle the message
		if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


	CSwordBibleDoc::bibleZoom = !(CSwordBibleDoc::bibleZoom);

	ZoomText();

}

void CParallelBible::OnUpdateZoom(CCmdUI *pCmdUI)
{
	pCmdUI->SetCheck(CSwordBibleDoc::bibleZoom);
	
}

void CParallelBible::ZoomText()
{
  if(CSwordBibleDoc::bibleZoom) m_browser.ZoomText(3);
  else m_browser.ZoomText(2);  // turn off zooming

}


// displays the text in the rich edit box of the one year bible
void CParallelBible::showText()
{
	sword::VerseKey key = CSwordBibleDoc::key;
          
	m_browser.Clear();

	// get the chapter
	int chap = (CSwordBibleDoc::key).Chapter();
	UINT b = key.Book();
    CString verse;
    CString heading;
    int b1 = CSwordBibleDoc::Book();
    heading.Format(_T("%s %d"), CSwordBibleDoc::bookCode[b1 - 1][0], chap);
    char start[20];
	const char* book = key.getBookAbbrev();
	sprintf(start, "%s %d:1", book, chap);
    BOOL Switch = TRUE;
	
		
   chapText = _T("<html>") + headText + _T("<body><h3>") + heading + _T("</h3><table border=\"0\"><tr bgcolor=#E0EEEE>");


   for(int i = 0; i < CSwordBibleDoc::numBiblesAvailable; i++)
			 if(CSwordBibleDoc::pHTMLBibleModule[i] && BibleActive[i]) 
			 {
          chapText += _T("<td><h4 align=\"center\">") + (CString) CSwordBibleDoc::pHTMLBibleModule[i]->Name() + _T("</h4></td>");
       }

       chapText += _T("</tr>");



	for (key = start; !key.Error() && key.Chapter() == chap && b ==  key.Book(); key++){

          if(Switch)	chapText += _T("<tr bgcolor=#F0F8FF>");
          else chapText += _T("<tr bgcolor=#FFFFF5>");

          Switch = !Switch;
          
          verse.Format(_T("<sup>%i</sup>"), key.Verse());

			for(int i = 0; i < CSwordBibleDoc::numBiblesAvailable; i++) {
			 if(CSwordBibleDoc::pHTMLBibleModule[i] && BibleActive[i]) 
			{
				
				CSwordBibleDoc::pHTMLBibleModule[i]->SetKey(key);             // set key to current verse

        

				chapText = chapText + _T("<td>") + verse + (CString) CSwordBibleDoc::pHTMLBibleModule[i]->RenderText() + _T("<br/></td>");

		   }
			}

			chapText+= _T("</tr>");

			}

			chapText += _T("</table></body></html>");

			m_browser.Write(chapText);

      ZoomText();
		
}



void CParallelBible::OnChangeVersions()
{


	showText();
	
}

void CParallelBible::OnShowVersions()
{

	RECT rc;
    m_wndFormatBar.GetToolBarCtrl().GetItemRect(0,&rc);
	ClientToScreen(&rc); // TrackPopupMenu uses screen coords

   CMenu menu;
   menu.CreatePopupMenu();
   CMenu* pPopup = NULL;
   pPopup = &menu;

   if(pPopup == NULL) return;
   int dwSelectionMade;  

 
   // fill in the strings for different bible versions
	for(int i = 0; i < CSwordBibleDoc::numBiblesAvailable; i++)
		if(CSwordBibleDoc::pRTFBibleModule[i] != NULL)
		{
			         pPopup->AppendMenu(MF_STRING,ID_BIBLEVERSION_NAMES + i, (CString) CSwordBibleDoc::pRTFBibleModule[i]->Description());
					 if(BibleActive[i]) pPopup->CheckMenuItem(ID_BIBLEVERSION_NAMES + i,MF_CHECKED); 

		}


         dwSelectionMade =  pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON|TPM_RETURNCMD, 
         rc.left, rc.bottom + 4, this);

	
		int selection = dwSelectionMade;
		int base = ID_BIBLEVERSION_NAMES;
		int activate = selection - base;


	if(activate >= 0 && activate < CSwordBibleDoc::numBiblesAvailable) 
	{
		BibleActive[activate] = !BibleActive[activate];
		showText();

	}
    pPopup->DestroyMenu(); 


}






BOOL CParallelBible::OnSetActive()
{
	headText.Format(_T("<head><style type=\"text/css\"> td {font: %dpt \"%s\";}</style></head>"),
		CBiblePage::font.text_facesize/2, CBiblePage::font.text_facename); 

  showText();
  return CPropertyPage::OnSetActive();
}

void CParallelBible::OnSelectAll()
{
		// only the active page should handle the message
  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

  m_browser.SelectAll(); 

}

BOOL CParallelBible::OnToolTipNotify(UINT id, NMHDR *pNMHDR,   LRESULT *pResult)
{
    ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);

     // if there is a top level routing frame then let it handle the message
     if (GetRoutingFrame() != NULL) return FALSE;

     // to be thorough we will need to handle UNICODE versions of the message also !!
     TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
     TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
     TCHAR szFullText[512];
     CString strTipText;
     UINT nID = pNMHDR->idFrom;

     if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
         pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
     {
          // idFrom is actually the HWND of the tool 
          nID = ::GetDlgCtrlID((HWND)nID);
     }

     if (nID != 0) // will be zero on a separator
     {
          AfxLoadString(nID, szFullText);
          strTipText=szFullText;

#ifndef _UNICODE
          if (pNMHDR->code == TTN_NEEDTEXTA)
          {
               lstrcpyn(pTTTA->szText, strTipText, sizeof(pTTTA->szText));
          }
          else
          {
               _mbstowcsz(pTTTW->szText, strTipText, sizeof(pTTTW->szText));
          }
#else
          if (pNMHDR->code == TTN_NEEDTEXTA)
          {
               _wcstombsz(pTTTA->szText, strTipText,sizeof(pTTTA->szText));
          }
          else
          {
               lstrcpyn(pTTTW->szText, strTipText, sizeof(pTTTW->szText));
          }
#endif

          *pResult = 0;

          // bring the tooltip window above other popup windows
          ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,SWP_NOACTIVATE|
               SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER); return TRUE;
     }
      return FALSE;
}

LONG CParallelBible::OnMainFrameCommand(UINT, LONG)
{
	// only the active page should handle the message
	if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return 0L;
  
	if(CBiblePage::ActiveMainFrameCommand == _T("ShowChapter")) showText();
	
	 return 0L;
}






BOOL CParallelBible::PreTranslateMessage(MSG* pMsg)
{
  
// We have a right click
  if (  (WM_RBUTTONDOWN == pMsg->message) ||
    (WM_RBUTTONDBLCLK == pMsg->message))
  {

    CPoint pt = pMsg->pt;
    ScreenToClient(&pt);

    if( rect.PtInRect(pt) == TRUE)
    {
      OnRightButtonDown();
      return TRUE;
    }
  }

  return CPropertyPage::PreTranslateMessage(pMsg);
}


void CParallelBible::OnRightButtonDown()
{
	  CPoint point;                                            
     ::GetCursorPos(&point); //where is the mouse?
     CMenu menu; //lets display out context menu :) 
     DWORD dwSelectionMade;                                       
     VERIFY(menu.LoadMenu(_T("IDR_MENU_PARALLEL")) );  
     CMenu *pmenuPopup = menu.GetSubMenu(0);
     ASSERT(pmenuPopup != NULL);   

	  if(CSwordBibleDoc::bibleZoom)	pmenuPopup->CheckMenuItem(ID_PARALLEL_ZOOM,MF_CHECKED); 
	 
     dwSelectionMade = pmenuPopup->TrackPopupMenu( (TPM_LEFTALIGN|TPM_LEFTBUTTON|
                                                      TPM_RETURNCMD),
                                                    point.x, point.y, this); 

	

	
	switch (dwSelectionMade)
	{
	case ID_PARALLEL_PRINT:			OnPrint(); break;
	case ID_PARALLEL_COPY:			OnCopy(); break;
	case ID_PARALLEL_SELECTALL:      OnSelectAll(); break;
	case ID_PARALLEL_ZOOM:			OnZoom(); break; 
	case ID_PARALLEL_PREVIOUS:		OnPrevious(); break;
	case ID_PARALLEL_NEXT:			OnNext(); break;

	}

	
	pmenuPopup->DestroyMenu(); 

}


BOOL CParallelBible::OnClickReference(CString ref)
{
  sword::URL url(ref);

  sword::SWBuf type = url.getParameterValue("type");

  if(type.compare('n') == 0 || type.compare('x') == 0 ){

  if(type.compare('n') == 0) type = "footnote";
  else type = "cross-reference";
    
  sword::SWBuf module = url.getParameterValue("module");
  sword::SWKey key =    url.getParameterValue("passage");
  sword::SWBuf footnoteNumber = url.getParameterValue("value");

 
 
  CString tip;
  int i = 0;
  BOOL found = FALSE;
  sword::SWBuf cur;
  while(found == FALSE && i < CSwordBibleDoc::numBiblesAvailable)
  {
    cur = CSwordBibleDoc::pRTFBibleModule[i]->Name();

    if(cur.compare(module) == 0) found = TRUE;
    else  i++;   

  }

  if(found == FALSE) return TRUE; // cancel navigation.


  CSwordBibleDoc::pRTFBibleModule[i]->SetKey(key);
  CSwordBibleDoc::pRTFBibleModule[i]->RenderText();  // resolve key
  

  if(type == "cross-reference")  {
	  sword::SWBuf text = CSwordBibleDoc::pRTFBibleModule[i]->getEntryAttributes()["Footnote"][footnoteNumber]["refList"];
	  CBiblePage::DisplayReferenceVerses((CString) text , tip);
  }
  


  else {

  sword::SWBuf text = CSwordBibleDoc::pRTFBibleModule[i]->getEntryAttributes()["Footnote"][footnoteNumber]["body"];

  CString fs;
	fs.Format(_T("\\fs%d "),22);
 tip = CBiblePage::font.GetHeaderRTF() + fs + _T("\\f2\\cf7\\b ") + key.getText() + _T(" (") 
    + (CString) CSwordBibleDoc::pRTFBibleModule[i]->Description() + _T(")\\par\\par\\b0\\cf8 ") 
			 + (CString) CSwordBibleDoc::pRTFBibleModule[i]->RenderText(text) + _T("}"); 	
   }

  CBibleSheet::DisplayReference(type.c_str(), tip);

  return TRUE;  // cancel navigation
  }

  return FALSE;    // continue navigation
}

